﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media.Media3D;
using System.Collections.ObjectModel;
using SkeletalAnimation3D.Core;

namespace SkeletalAnimation3D
{
    public class BoneInfo : DependencyObject
    {
        public int Id
        {
            get { return (int)GetValue(IdProperty); }
            set { SetValue(IdProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Id.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IdProperty =
            DependencyProperty.Register("Id", typeof(int), typeof(BoneInfo), new UIPropertyMetadata(0));


        public Point3D Position
        {
            get { return (Point3D)GetValue(PositionProperty); }
            set { SetValue(PositionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Position.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PositionProperty =
            DependencyProperty.Register("Position", typeof(Point3D), typeof(BoneInfo), new UIPropertyMetadata(new Point3D()));


        public Quaternion Orientation
        {
            get { return (Quaternion)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Orientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(Quaternion), typeof(BoneInfo), new UIPropertyMetadata(Quaternion.Identity));


        public string Name
        {
            get { return (string)GetValue(NameProperty); }
            set { SetValue(NameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Name.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty NameProperty =
            DependencyProperty.Register("Name", typeof(string), typeof(BoneInfo), new UIPropertyMetadata(String.Empty));



        public double Size
        {
            get { return (double)GetValue(SizeProperty); }
            set { SetValue(SizeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Size.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SizeProperty =
            DependencyProperty.Register("Size", typeof(double), typeof(BoneInfo), new UIPropertyMetadata(1.0));



        public ObservableCollection<BoneInfo> Children
        {
            get { return (ObservableCollection<BoneInfo>)GetValue(ChildrenProperty); }
            set { SetValue(ChildrenProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Children.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ChildrenProperty =
            DependencyProperty.Register("Children", typeof(ObservableCollection<BoneInfo>), typeof(BoneInfo), new UIPropertyMetadata(null));



        public BoneInfo Parent
        {
            get { return (BoneInfo)GetValue(ParentProperty); }
            set { SetValue(ParentProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Parent.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ParentProperty =
            DependencyProperty.Register("Parent", typeof(BoneInfo), typeof(BoneInfo), new UIPropertyMetadata(null));


        internal bool SetOrientation(int boneId, Quaternion orientation)
        {
            if (boneId == Id)
            {
                Orientation = orientation;
                return true;
            }
            else
            {
                if (Children != null)
                {
                    for (int i = 0; i < Children.Count; i++)
                    {
                        if (Children[i].SetOrientation(boneId, orientation))
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
        }

        
        internal BoneInfo GetBone(int id)
        {
            if (Id == id)
            {
                return this;
            }
            else
            {
                if (Children != null && Children.Count > 0)
                {
                    for (int i = 0; i < Children.Count; i++)
                    {
                        BoneInfo result = Children[i].GetBone(id);
                        if (result != null)
                        {
                            return result;
                        }
                    }
                }
                return null;
            }
        }
    }
}
